import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class GameWorld {
    public static final int GRID_SIZE = 70;
    public static final int GROUND_ROWS = 1;
    public static final int BACKGROUND_SPEED = 1;
    public static final int GROUND_SPEED = 2;

    private Image background;
    private Image grass;
    private int backgroundX = 0;
    private int groundOffset = 0;
    private boolean[][] groundGrid;
    private int groundWidth;
    private Random random = new Random();
    private static final int MIN_GAP_DISTANCE = 15;
    private static final int MAX_GAP_DISTANCE = 25;
    private static int MIN_WALL_DISTANCE = 6;
    private static int MAX_WALL_DISTANCE = 11;
    private static final int MIN_BAT_DISTANCE = 10;
    private static final int MAX_BAT_DISTANCE = 20;
    private int score = 9500;
    private List<Bat> bats = new ArrayList<>();
    private int nextBatPos = 0;

    private Image stone;
    private Image stoneBroken;
    private Image stoneBroken2;
    private Image background2;
    private Image stoneGround;
    private boolean useAlternateTheme = false;

    private List<Image> batFrames = new ArrayList<>();
    private static final int BAT_ANIMATION_SPEED = 8;
    private long lastGapTime = 0;
    private long lastWallTime = 0;
    private long lastBatTime = 0;
    private static final long OBSTACLE_COOLDOWN = 800;

    private Image shieldImage;
    private Shield shield;
    private long lastShieldTime = 0;
    private static final int SHIELD_SPAWN_INTERVAL = 3000;
    private int hideScore = 0;
    private boolean shouldTrySpawnShield = false;

    private List<Gap> gaps = new ArrayList<>();
    private List<StoneWall> stoneWalls = new ArrayList<>();
    private int nextGapPos = 0;
    private int nextWallPos = 0;
    private Player player;

    private Boss boss;
    private boolean bossFightActive = false;
    private long bossDefeatedTime = 0;
    private static final long POST_BOSS_DURATION = 2000;
    private boolean bossDefeated = false;

    public GameWorld(Player player) {
        loadImages();
        initGround();
        boss = new Boss();
        this.player = player;
        try {
            stone = new Image(getClass().getResourceAsStream("/images/stump.png"));
            stoneBroken = new Image(getClass().getResourceAsStream("/images/stump-broken.png"));
            stoneBroken2 = new Image(getClass().getResourceAsStream("/images/stump-broken2.png"));
            shieldImage = new Image(getClass().getResourceAsStream("/images/hudun.png"));
        } catch (Exception e) {
            System.err.println("加载石墙图像失败: " + e.getMessage());
        }

        reset();
    }

    public int getScore(){
        return score;
    }
    public void setScore(int score){
        this.score=score;
    }

    private void loadImages() {
        try {
            background = new Image(getClass().getResourceAsStream("/images/background1.png"));
            background2 = new Image(getClass().getResourceAsStream("/images/background2.png"));
            grass = new Image(getClass().getResourceAsStream("/images/grass.png"));
            stoneGround = new Image(getClass().getResourceAsStream("/images/stone.png"));

            // 加载蝙蝠动画帧
            batFrames.add(new Image(getClass().getResourceAsStream("/images/bat1.png")));
            batFrames.add(new Image(getClass().getResourceAsStream("/images/bat2.png")));
            batFrames.add(new Image(getClass().getResourceAsStream("/images/bat3.png")));
            batFrames.add(new Image(getClass().getResourceAsStream("/images/bat4.png")));
        } catch (Exception e) {
            System.err.println("加载世界图像资源失败: " + e.getMessage());
            System.exit(1);
        }
    }

    private void initGround() {
        groundWidth = (int) Math.ceil(GameConstants.getScreenWidth() / (double) GRID_SIZE) + 2 + 4;
        groundGrid = new boolean[GROUND_ROWS][groundWidth];
        reset();
    }

    public void render(GraphicsContext gc) {
        // 绘制背景
        int screenHeight = GameConstants.getScreenHeight();
        int screenCols = (int) Math.ceil(GameConstants.getScreenWidth() / (double) GRID_SIZE) + 1;

        Image currentBackground = useAlternateTheme ? background2 : background;
        gc.drawImage(currentBackground, backgroundX, 0);
        gc.drawImage(currentBackground, backgroundX + currentBackground.getWidth(), 0);

        // 绘制地面
        for (int col = 0; col < screenCols; col++) {
            if (groundGrid[0][col]) {
                int x = col * GRID_SIZE + groundOffset;
                Image groundImage = useAlternateTheme ? stoneGround : grass;
                gc.drawImage(groundImage, x, screenHeight - GRID_SIZE, GRID_SIZE, GRID_SIZE);
            }
        }

        // BOSS战期间只渲染背景和BOSS
        if (bossFightActive) {
            boss.render(gc);
            player.renderBombs(gc);
            return;
        }

        // 渲染石墙
        for (StoneWall wall : stoneWalls) {
            wall.render(gc, screenHeight, GRID_SIZE);
        }

        // 渲染蝙蝠
        for (Bat bat : bats) {
            bat.render(gc, screenHeight, GRID_SIZE);
        }

        // 渲染护盾
        if (shield != null && shield.active) {
            double shieldY = screenHeight - GRID_SIZE * 1.8;
            gc.drawImage(shieldImage, shield.x, shieldY, GRID_SIZE, GRID_SIZE);
        }
    }

    // 添加护盾碰撞检测
    public boolean checkShieldCollision(int playerX, int playerY, int width, int height) {
        if (shield != null && shield.active) {
            double shieldY = GameConstants.getScreenHeight() - GameWorld.GRID_SIZE * 1.8;
            if (playerX + width > shield.x &&
                    playerX < shield.x + GRID_SIZE &&
                    playerY + height > shieldY &&
                    playerY < shieldY + GRID_SIZE) {
                shield.active = false;
                return true;
            }
        }
        return false;
    }

    public void update(double deltaTime) {
        if (GameConstants.GAME_PAUSED) {
            return;
        }

        // 检查是否激活BOSS战
        if (!bossFightActive && !bossDefeated && score >= 10000) {
            bossFightActive = true;
            boss.activate(GameConstants.getScreenWidth(), GameConstants.getScreenHeight());
        }

        // BOSS战逻辑
        if (bossFightActive) {
            boss.update();
            // 更新玩家炸弹
            for (Bomb bomb : player.getBombs()) {
                bomb.update();
                boss.checkHit(bomb);
            }

            // 检查BOSS是否被击败
            if (!boss.isActive() && bossDefeatedTime == 0) {
                bossDefeatedTime = System.currentTimeMillis();
                bossDefeated = true; // 标记BOSS已被击败
            }

            // BOSS战结束后恢复普通模式
            if (bossDefeatedTime > 0 &&
                    System.currentTimeMillis() - bossDefeatedTime > POST_BOSS_DURATION) {
                bossFightActive = false;
                bossDefeatedTime = 0;
                // 重置分数到略低于10000，避免立即再次触发BOSS战
                score = 9999;
            }

            return; // BOSS战期间不更新普通游戏世界
        }

        if (score >= 5000 && !useAlternateTheme) {
            useAlternateTheme = true;
            MIN_WALL_DISTANCE = 15;
            MAX_WALL_DISTANCE = 25;
        } else if (score < 5000 && useAlternateTheme) {
            useAlternateTheme = false;
        }

        float speedFactor = GameConstants.GAME_SPEED;
        backgroundX -= (int)(BACKGROUND_SPEED * speedFactor);
        if (backgroundX <= -background.getWidth()) {
            backgroundX = 0;
        }

        groundOffset -= (int)(GROUND_SPEED * speedFactor);

        // 更新石墙位置
        for (StoneWall wall : stoneWalls) {
            wall.update((int)(GROUND_SPEED * speedFactor));
        }

        if (groundOffset <= -GRID_SIZE) {
            groundOffset = 0;
            shiftGround();
        }

        // 更新蝙蝠位置
        for (Bat bat : bats) {
            bat.update((int)(GROUND_SPEED * speedFactor));
        }

        //护盾生成
        if (hideScore>=3000 && shield == null) {
            shouldTrySpawnShield = true;
        }

        if (shouldTrySpawnShield && shield == null) {
            if (trySpawnShield()) {
                shouldTrySpawnShield = false;
                hideScore = 0;
            }
        }

        if (shield != null) {
            shield.x -= (int)(GROUND_SPEED * GameConstants.GAME_SPEED);
            if (shield.x + GRID_SIZE < -groundOffset) {
                shield = null;
            }
        }

        // 移除屏幕外的蝙蝠和石墙
        bats.removeIf(bat -> bat.getX() + GRID_SIZE < 0);
        stoneWalls.removeIf(wall -> wall.getX() + GRID_SIZE < 0);
    }

    private boolean shouldSpawnShield() {
        long currentTime = System.currentTimeMillis();
        return currentTime - lastGapTime > OBSTACLE_COOLDOWN &&
                currentTime - lastWallTime > OBSTACLE_COOLDOWN &&
                currentTime - lastBatTime > OBSTACLE_COOLDOWN &&
                currentTime - lastShieldTime > SHIELD_SPAWN_INTERVAL * 10;
    }

    private boolean trySpawnShield() {
        int screenRightCol = (int) Math.ceil(GameConstants.getScreenWidth() / (double) GRID_SIZE) + 1;
        int spawnX = GameConstants.getScreenWidth() + GRID_SIZE;
        int gridX = (spawnX - groundOffset) / GRID_SIZE;

        if(gridX >= groundWidth || !groundGrid[0][gridX]) {
            return false;
        }

        boolean positionSafe = true;
        for (StoneWall wall : stoneWalls) {
            if (Math.abs(wall.getX() - (screenRightCol * GRID_SIZE + groundOffset)) < GRID_SIZE * 3) {
                positionSafe = false;
                break;
            }
        }
        for (Bat bat : bats) {
            if (Math.abs(bat.getX() - (screenRightCol * GRID_SIZE + groundOffset)) < GRID_SIZE * 3) {
                positionSafe = false;
                break;
            }
        }

        boolean canSpawn = groundGrid[0][screenRightCol] &&
                shouldSpawnShield() &&
                positionSafe;

        if (canSpawn) {
            shield = new Shield();
            shield.x = screenRightCol * GRID_SIZE + groundOffset;
            lastShieldTime = System.currentTimeMillis();
            return true;
        }
        return false;
    }

    private void shiftGround() {
        for (int row = 0; row < GROUND_ROWS; row++) {
            for (int col = 0; col < groundWidth - 1; col++) {
                groundGrid[row][col] = groundGrid[row][col + 1];
                score++;
                hideScore++;
            }
            groundGrid[row][groundWidth - 1] = true;
        }

        long currentTime = System.currentTimeMillis();

        // 生成缺口
        if (--nextGapPos <= 0 && currentTime - lastGapTime > OBSTACLE_COOLDOWN
                && currentTime - lastWallTime > 1000
                && currentTime - lastBatTime > 1000) {
            int gapWidth = random.nextBoolean() ? 3 : 4;
            int gapStart = groundWidth - gapWidth;

            for (int i = 0; i < gapWidth; i++) {
                if (gapStart + i < groundWidth) {
                    groundGrid[0][gapStart + i] = false;
                }
            }
            gaps.add(new Gap(gapStart, gapWidth));
            nextGapPos = random.nextInt(MAX_GAP_DISTANCE - MIN_GAP_DISTANCE) + MIN_GAP_DISTANCE;
            lastGapTime = currentTime;
        }

        // 生成石墙
        if (--nextWallPos <= 0 && currentTime - lastWallTime > OBSTACLE_COOLDOWN
                && currentTime - lastGapTime > 1500
                && currentTime - lastBatTime > 1000) {
            int screenRightCol = (int) Math.ceil(GameConstants.getScreenWidth() / (double) GRID_SIZE) + 1;

            if (groundGrid[0][screenRightCol]) {
                stoneWalls.add(new StoneWall(
                        screenRightCol * GRID_SIZE + groundOffset,
                        stone, stoneBroken, stoneBroken2
                ));
                nextWallPos = random.nextInt(MAX_WALL_DISTANCE - MIN_WALL_DISTANCE) + MIN_WALL_DISTANCE;
                lastWallTime = currentTime;
            }
        }

        // 生成蝙蝠
        if (score >= 5000 && --nextBatPos <= 0 && currentTime - lastBatTime > OBSTACLE_COOLDOWN
                && currentTime - lastGapTime > 1500
                && currentTime - lastWallTime > 1000) {
            int screenRightCol = (int) Math.ceil(GameConstants.getScreenWidth() / (double) GRID_SIZE) + 1;

            if (groundGrid[0][screenRightCol]) {
                bats.add(new Bat(
                        screenRightCol * GRID_SIZE + groundOffset,
                        batFrames
                ));
                nextBatPos = random.nextInt(MAX_BAT_DISTANCE - MIN_BAT_DISTANCE) + MIN_BAT_DISTANCE;
                lastBatTime = currentTime;
            }
        }
    }

    public void reset() {
        backgroundX = 0;
        groundOffset = 0;
        useAlternateTheme = false;
        shield = null;
        hideScore = 0;
        shouldTrySpawnShield = false;
        bossDefeated = false; // 重置BOSS击败标志

        for (int row = 0; row < GROUND_ROWS; row++) {
            for (int col = 0; col < groundWidth; col++) {
                groundGrid[row][col] = true;
            }
        }

        stoneWalls.clear();
        bats.clear();
        gaps.clear();
        nextGapPos = random.nextInt(MAX_GAP_DISTANCE - MIN_GAP_DISTANCE) + MIN_GAP_DISTANCE;
        nextWallPos = random.nextInt(MAX_WALL_DISTANCE - MIN_WALL_DISTANCE) + MIN_WALL_DISTANCE;
    }

    public boolean isSolidGround(int playerX, int playerY) {
        int gridX = (playerX - groundOffset) / GRID_SIZE;
        if (gridX >= 0 && gridX < groundWidth) {
            // 检查是否有缺口
            for (Gap gap : gaps) {
                if (gap.isPositionInGap(gridX)) {
                    return false;
                }
            }
            return groundGrid[0][gridX];
        }
        return false;
    }

    public boolean checkBatCollision(int playerX, int playerY, int width, int height, boolean isPlayerSliding) {
        for (Bat bat : bats) {
            if (bat.checkCollision(playerX, playerY, width, height, isPlayerSliding, GRID_SIZE)) {
                return true;
            }
        }
        return false;
    }

    public boolean checkWallCollision(int playerX, int playerY, int width, int height) {
        for (StoneWall wall : stoneWalls) {
            if (wall.checkCollision(playerX, playerY, width, height, GRID_SIZE)) {
                return true;
            }
        }
        return false;
    }

    public boolean checkBombCollision(Bomb bomb) {
        // 检查与石墙碰撞
        for (StoneWall wall : stoneWalls) {
            if (wall.checkBombCollision(bomb, GRID_SIZE)) {
                return true;
            }
        }

        // 检查与蝙蝠碰撞
        for (Bat bat : bats) {
            if (bat.checkBombCollision(bomb, GRID_SIZE)) {
                bat.health--;
                if (bat.health <= 0) {
                    bat.active = false;
                }
                return true;
            }
        }
        return false;
    }

    public boolean isBossFightActive() {
        return bossFightActive;
    }

    public Boss getBoss() {
        return boss;
    }
    public int getGroundY() {
        return GameConstants.getGroundY();
    }

    public void setBossFightActive(boolean b) {
        bossFightActive=b;
    }

    // 护盾内部类保持不变
    private class Shield {
        int x;
        boolean active = true;
    }
}